From 17872fb72e5a54102cc0d0b9a6914c0d3389cf30 Mon Sep 17 00:00:00 2001 From: "djm@kirby.fc.hp.com" Date: Wed, 1 Jun 2005 20:11:09 +0000 Subject: [PATCH] bitkeeper revision 1.1564.1.6 (429e165dilv2Yl2AOW9ZyHrCpVrJDg) Add counters for hyperprivops and reflections Preliminary work for fast break reflection Signed-off by: Dan Magenheimer --- xen/arch/ia64/asm-offsets.c | 7 +++ xen/arch/ia64/dom_fw.c | 4 +- xen/arch/ia64/domain.c | 5 +- xen/arch/ia64/hyperprivop.S | 88 ++++++++++++++++++++++++++++++++++- xen/arch/ia64/ivt.S | 26 +++++++---- xen/arch/ia64/privop.c | 6 ++- xen/arch/ia64/process.c | 41 +++++++++++++++- xen/include/asm-ia64/domain.h | 2 +- 8 files changed, 159 insertions(+), 20 deletions(-) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index 6518e29bdb..d2e5fcff4e 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -45,10 +45,15 @@ void foo(void) DEFINE(XSI_PSR_IC, (SHAREDINFO_ADDR+offsetof(vcpu_info_t, arch.interrupt_collection_enabled))); DEFINE(XSI_PSR_I_OFS, offsetof(vcpu_info_t, arch.interrupt_delivery_enabled)); DEFINE(XSI_IIP_OFS, offsetof(vcpu_info_t, arch.iip)); + DEFINE(XSI_IPSR, (SHAREDINFO_ADDR+offsetof(vcpu_info_t, arch.ipsr))); DEFINE(XSI_IPSR_OFS, offsetof(vcpu_info_t, arch.ipsr)); DEFINE(XSI_IFS_OFS, offsetof(vcpu_info_t, arch.ifs)); + DEFINE(XSI_IIM_OFS, offsetof(vcpu_info_t, arch.iim)); DEFINE(XSI_BANKNUM_OFS, offsetof(vcpu_info_t, arch.banknum)); + DEFINE(XSI_BANK0_OFS, offsetof(vcpu_info_t, arch.bank0_regs[0])); + DEFINE(XSI_BANK1_OFS, offsetof(vcpu_info_t, arch.bank1_regs[0])); DEFINE(XSI_METAPHYS_OFS, offsetof(vcpu_info_t, arch.metaphysical_mode)); + DEFINE(XSI_PRECOVER_IFS_OFS, offsetof(vcpu_info_t, arch.precover_ifs)); DEFINE(XSI_INCOMPL_REG_OFS, offsetof(vcpu_info_t, arch.incomplete_regframe)); DEFINE(XSI_PEND_OFS, offsetof(vcpu_info_t, arch.pending_interruption)); DEFINE(XSI_RR0_OFS, offsetof(vcpu_info_t, arch.rrs[0])); @@ -66,6 +71,8 @@ void foo(void) DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct exec_domain, arch.metaphysical_rr0)); DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct exec_domain, arch.metaphysical_saved_rr0)); + DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct exec_domain, arch.breakimm)); + DEFINE(IA64_VCPU_IVA_OFFSET, offsetof (struct exec_domain, arch.iva)); BLANK(); diff --git a/xen/arch/ia64/dom_fw.c b/xen/arch/ia64/dom_fw.c index 65f245d870..b57a727a50 100644 --- a/xen/arch/ia64/dom_fw.c +++ b/xen/arch/ia64/dom_fw.c @@ -50,7 +50,7 @@ void dom_efi_hypercall_patch(struct domain *d, unsigned long paddr, unsigned lon if (d == dom0) paddr += dom0_start; imva = domain_mpa_to_imva(d,paddr); - build_hypercall_bundle(imva,d->breakimm,hypercall,1); + build_hypercall_bundle(imva,d->arch.breakimm,hypercall,1); } @@ -61,7 +61,7 @@ void dom_fw_hypercall_patch(struct domain *d, unsigned long paddr, unsigned long if (d == dom0) paddr += dom0_start; imva = domain_mpa_to_imva(d,paddr); - build_hypercall_bundle(imva,d->breakimm,hypercall,ret); + build_hypercall_bundle(imva,d->arch.breakimm,hypercall,ret); } diff --git a/xen/arch/ia64/domain.c b/xen/arch/ia64/domain.c index 30a7a45dd1..cc879a4f6f 100644 --- a/xen/arch/ia64/domain.c +++ b/xen/arch/ia64/domain.c @@ -210,7 +210,7 @@ void arch_do_createdomain(struct exec_domain *ed) */ d->xen_vastart = 0xf000000000000000; d->xen_vaend = 0xf300000000000000; - d->breakimm = 0x1000; + d->arch.breakimm = 0x1000; // stay on kernel stack because may get interrupts! // ia64_ret_from_clone (which b0 gets in new_thread) switches @@ -256,7 +256,8 @@ void arch_do_createdomain(struct exec_domain *ed) d->xen_vastart = 0xf000000000000000; d->xen_vaend = 0xf300000000000000; d->shared_info_va = 0xf100000000000000; - d->breakimm = 0x1000; + d->arch.breakimm = 0x1000; + ed->arch.breakimm = d->arch.breakimm; // stay on kernel stack because may get interrupts! // ia64_ret_from_clone (which b0 gets in new_thread) switches // to user stack diff --git a/xen/arch/ia64/hyperprivop.S b/xen/arch/ia64/hyperprivop.S index a33518e0ac..cbb8b39e4c 100644 --- a/xen/arch/ia64/hyperprivop.S +++ b/xen/arch/ia64/hyperprivop.S @@ -62,6 +62,92 @@ GLOBAL_ENTRY(fast_hyperprivop) // if not one of the above, give up for now and do it the slow way br.sptk.many dispatch_break_fault ;; +// reflect domain breaks directly to domain +// FIXME: DOES NOT WORK YET +// r16 == cr.isr +// r17 == cr.iim +// r18 == XSI_PSR_IC +// r19 == vpsr.ic (low 32 bits) | vpsr.i (high 32 bits) +// r22 == IA64_KR(CURRENT)+IA64_VCPU_BREAKIMM_OFFSET +// r31 == pr +GLOBAL_ENTRY(fast_break_reflect) + mov r20=cr.ipsr;; + // if big-endian domain or privileged-perfmon bits set, do slow way + extr.u r21=r20,IA64_PSR_BE_BIT,1 ;; + cmp.ne p7,p0=r21,r0 +(p7) br.sptk.many dispatch_break_fault ;; + extr.u r21=r20,IA64_PSR_PP_BIT,1 ;; + cmp.ne p7,p0=r21,r0 +(p7) br.sptk.many dispatch_break_fault ;; + // ensure ipsr.cpl==2, ipsr.ri==0 + // FIXME: any other psr bits need to be properly set/validated? + // ...see process.c: DELIVER_PSR_CLR/SET + extr.u r21=r20,IA64_PSR_CPL0_BIT,2;; + extr.u r23=r20,IA64_PSR_RI_BIT,2;; + dep r20=-1,r20,IA64_PSR_CPL1_BIT,1 ;; + dep r20=0,r20,IA64_PSR_CPL0_BIT,1 ;; + dep r20=0,r20,IA64_PSR_RI_BIT,2 ;; + mov cr.ipsr=r20;; + // save ipsr in shared_info, vipsr.cpl==(ipsr.cpl==3)?3:0 + cmp.ne p7,p0=3,r21;; +(p7) mov r21=r0 + dep r20=r21,r20,IA64_PSR_CPL0_BIT,2 ;; + dep r20=r23,r20,IA64_PSR_RI_BIT,2 ;; + // vipsr.i=vpsr.i + adds r21=XSI_PSR_I_OFS-XSI_PSR_IC_OFS,r18 ;; + ld4 r21=[r21];; + dep r20=r21,r20,IA64_PSR_I_BIT,1 ;; + adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; + // FIXME: any other vpsr bits need to be properly set/validated? + st8 [r21]=r20;; + // save iim in shared_info + adds r21=XSI_IIM_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r17;; + // save iip in shared_info + mov r20=cr.iip;; + adds r21=XSI_IIP_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r20;; + // save ifs in shared_info + adds r21=XSI_INCOMPL_REG_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r21]=r0 ;; + adds r21=XSI_IFS_OFS-XSI_PSR_IC_OFS,r18 + st8 [r21]=r0 ;; + cover ;; + mov r20=cr.ifs;; + adds r21=XSI_PRECOVER_IFS_OFS-XSI_PSR_IC_OFS,r18 ;; + st8 [r21]=r20;; + // vpsr.i = vpsr.ic = 0 on delivery of interruption + st8 [r18]=r0;; + // FIXME: need to save iipa and isr to be arch-compliant + // set iip to go to domain IVA break instruction vector + adds r22=IA64_VCPU_IVA_OFFSET-IA64_VCPU_BREAKIMM_OFFSET,r22;; + ld8 r23=[r22];; + movl r24=0x2c00;; + add r24=r24,r23;; + mov cr.iip=r24;; + // OK, now all set to go except for switch to virtual bank0 + mov r30=r2; mov r29=r3;; + adds r2=XSI_BANK1_OFS-XSI_PSR_IC_OFS,r18; + adds r3=(XSI_BANK1_OFS+8)-XSI_PSR_IC_OFS,r18;; + bsw.1;; + st8 [r2]=r16,16; st8 [r3]=r17,16 ;; + st8 [r2]=r18,16; st8 [r3]=r19,16 ;; + st8 [r2]=r20,16; st8 [r3]=r21,16 ;; + st8 [r2]=r22,16; st8 [r3]=r23,16 ;; + st8 [r2]=r24,16; st8 [r3]=r25,16 ;; + st8 [r2]=r26,16; st8 [r3]=r27,16 ;; + st8 [r2]=r28,16; st8 [r3]=r29,16 ;; + st8 [r2]=r30,16; st8 [r3]=r31,16 ;; + movl r31=XSI_IPSR;; + bsw.0 ;; + mov r2=r30; mov r3=r29;; + adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; + st4 [r20]=r0 ;; + mov pr=r31,-1 ;; + rfi + ;; + + // ensure that, if giving up, registers at entry to fast_hyperprivop unchanged ENTRY(hyper_rfi) #define FAST_HYPERPRIVOP_CNT @@ -112,8 +198,6 @@ ENTRY(hyper_rfi) ld8 r20=[r20];; dep r20=0,r20,38,25;; // ensure ifs has no reserved bits set mov cr.ifs=r20 ;; -// TODO: increment a counter so we can count how many rfi's go the fast way -// but where? counter must be pinned // ipsr.cpl == (vcr.ipsr.cpl == 0) 2 : 3; dep r21=-1,r21,IA64_PSR_CPL1_BIT,1 ;; // vpsr.i = vcr.ipsr.i; vpsr.ic = vcr.ipsr.ic diff --git a/xen/arch/ia64/ivt.S b/xen/arch/ia64/ivt.S index 0938f6075e..e78e7f96b9 100644 --- a/xen/arch/ia64/ivt.S +++ b/xen/arch/ia64/ivt.S @@ -783,20 +783,26 @@ ENTRY(break_fault) ld8 r19=[r18] ;; cmp.eq p7,p0=r0,r17 // is this a psuedo-cover? -(p7) br.sptk.many dispatch_privop_fault +(p7) br.spnt.many dispatch_privop_fault ;; - cmp4.ne p7,p0=r0,r19 -(p7) br.sptk.many dispatch_break_fault - // If we get to here, we have a hyperprivop - // For now, hyperprivops are handled through the break mechanism - // Later, they will be fast hand-coded assembly with psr.ic off + // if vpsr.ic is off, we have a hyperprivop + // A hyperprivop is hand-coded assembly with psr.ic off // which means no calls, no use of r1-r15 and no memory accesses // except to pinned addresses! -#define FAST_HYPERPRIVOPS -#ifdef FAST_HYPERPRIVOPS - br.sptk.many fast_hyperprivop + cmp4.eq p7,p0=r0,r19 +(p7) br.sptk.many fast_hyperprivop + ;; + mov r22=IA64_KR(CURRENT);; + adds r22=IA64_VCPU_BREAKIMM_OFFSET,r22;; + ld4 r23=[r22];; + cmp4.eq p6,p7=r23,r17 // Xen-reserved breakimm? +(p6) br.spnt.many dispatch_break_fault + ;; +//#define FAST_BREAK +#ifdef FAST_BREAK + br.sptk.many fast_break_reflect #else - br.sptk.many dispatch_break_fault + br.spnt.many dispatch_break_fault #endif ;; #endif diff --git a/xen/arch/ia64/privop.c b/xen/arch/ia64/privop.c index d0be05d9e4..c989eb1cbc 100644 --- a/xen/arch/ia64/privop.c +++ b/xen/arch/ia64/privop.c @@ -987,14 +987,14 @@ int dump_hyperprivop_counts(char *buf) char *s = buf; unsigned long total = 0; for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += slow_hyperpriv_cnt[i]; - s += sprintf(s,"Slow hyperprivops (total %d:\n",total); + s += sprintf(s,"Slow hyperprivops (total %d):\n",total); for (i = 1; i <= HYPERPRIVOP_MAX; i++) if (slow_hyperpriv_cnt[i]) s += sprintf(s,"%10d %s\n", slow_hyperpriv_cnt[i], hyperpriv_str[i]); total = 0; for (i = 1; i <= HYPERPRIVOP_MAX; i++) total += fast_hyperpriv_cnt[i]; - s += sprintf(s,"Fast hyperprivops (total %d:\n",total); + s += sprintf(s,"Fast hyperprivops (total %d):\n",total); for (i = 1; i <= HYPERPRIVOP_MAX; i++) if (fast_hyperpriv_cnt[i]) s += sprintf(s,"%10d %s\n", @@ -1016,6 +1016,7 @@ int dump_privop_counts_to_user(char __user *ubuf, int len) int n = dump_privop_counts(buf); n += dump_hyperprivop_counts(buf + n); + n += dump_reflect_counts(buf + n); #ifdef PRIVOP_ADDR_COUNT n += dump_privop_addrs(buf + n); #endif @@ -1033,6 +1034,7 @@ int zero_privop_counts_to_user(char __user *ubuf, int len) #ifdef PRIVOP_ADDR_COUNT zero_privop_addrs(); #endif + zero_reflect_counts(); if (len < TMPBUFLEN) return -1; if (__copy_to_user(ubuf,buf,n)) return -1; return n; diff --git a/xen/arch/ia64/process.c b/xen/arch/ia64/process.c index 60a2f30f76..f1655b2580 100644 --- a/xen/arch/ia64/process.c +++ b/xen/arch/ia64/process.c @@ -130,6 +130,42 @@ unsigned long translate_domain_mpaddr(unsigned long mpaddr) return ((pteval & _PAGE_PPN_MASK) | (mpaddr & ~PAGE_MASK)); } +unsigned long slow_reflect_count[0x80] = { 0 }; +unsigned long fast_reflect_count[0x80] = { 0 }; + +#define inc_slow_reflect_count(vec) slow_reflect_count[vec>>8]++; + +void zero_reflect_counts(void) +{ + int i; + for (i=0; i<0x80; i++) slow_reflect_count[i] = 0; + for (i=0; i<0x80; i++) fast_reflect_count[i] = 0; +} + +int dump_reflect_counts(char *buf) +{ + int i,j,cnt; + char *s = buf; + + s += sprintf(s,"Slow reflections by vector:\n"); + for (i = 0, j = 0; i < 0x80; i++) { + if (cnt = slow_reflect_count[i]) { + s += sprintf(s,"0x%02x00:%10d, ",i,cnt); + if ((j++ & 3) == 3) s += sprintf(s,"\n"); + } + } + if (j & 3) s += sprintf(s,"\n"); + s += sprintf(s,"Fast reflections by vector:\n"); + for (i = 0, j = 0; i < 0x80; i++) { + if (cnt = fast_reflect_count[i]) { + s += sprintf(s,"0x%02x00:%10d, ",i,cnt); + if ((j++ & 3) == 3) s += sprintf(s,"\n"); + } + } + if (j & 3) s += sprintf(s,"\n"); + return s - buf; +} + void reflect_interruption(unsigned long ifa, unsigned long isr, unsigned long itiriim, struct pt_regs *regs, unsigned long vector) { unsigned long vcpu_get_ipsr_int_state(struct exec_domain *,unsigned long); @@ -165,6 +201,7 @@ panic_domain(regs,"psr.ic off, delivering fault=%lx,iip=%p,ifa=%p,isr=%p,PSCB.ii regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; // NOTE: nested trap must NOT pass PSCB address //regs->r31 = (unsigned long) &PSCB(ed); + inc_slow_reflect_count(vector); return; } @@ -195,6 +232,8 @@ panic_domain(regs,"psr.ic off, delivering fault=%lx,iip=%p,ifa=%p,isr=%p,PSCB.ii PSCB(ed,interrupt_delivery_enabled) = 0; PSCB(ed,interrupt_collection_enabled) = 0; + + inc_slow_reflect_count(vector); } void foodpi(void) {} @@ -748,7 +787,7 @@ ia64_handle_break (unsigned long ifa, struct pt_regs *regs, unsigned long isr, u if (running_on_sim) do_ssc(vcpu_get_gr(current,36), regs); else do_ssc(vcpu_get_gr(current,36), regs); } - else if (iim == d->breakimm) { + else if (iim == d->arch.breakimm) { if (ia64_hypercall(regs)) vcpu_increment_iip(current); } diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index d361b34090..88de406adc 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -49,7 +49,6 @@ struct arch_domain { #define starting_rid arch.starting_rid #define ending_rid arch.ending_rid #define rid_bits arch.rid_bits -#define breakimm arch.breakimm #define xen_vastart arch.xen_vastart #define xen_vaend arch.xen_vaend #define shared_info_va arch.shared_info_va @@ -75,6 +74,7 @@ struct arch_exec_domain { void *regs; /* temporary until find a better way to do privops */ int metaphysical_rr0; // from arch_domain (so is pinned) int metaphysical_saved_rr0; // from arch_domain (so is pinned) + int breakimm; // from arch_domain (so is pinned) struct mm_struct *active_mm; struct thread_struct _thread; // this must be last #ifdef CONFIG_VTI -- 2.30.2